/* \file
 * \brief Simulation frames.
 */

#ifndef MDS_FRAME_INCLUDED
#define MDS_FRAME_INCLUDED 1


#include "../mds/ini/position.h"
#include "../mds/ini/velocity.h"
#include "../mds/pnode.h"

#define MDS_POSITION      0
#define MDS_VELOCITY      1
#define MDS_ACCELERATION  2
#define MDS_PREV_ACCELER  3
#define MDS_AGED_ACCELER  4



/** \brief One simulation frame. */
typedef struct
{
	size_t            num_particles;  /*!< particles in each set    */
	size_t            num_sets;       /*!< number of sets           */
	mds_vector_set   *sets;           /*!< all the sets             */
	size_t            reserved;       /*!< reserved for memory      */
	mds_pnode        *nodes;          /*!< keep track of particles  */  
	mds_vector        box;            /*!< current simulation box   */
	mds_pbc_proc      pbc_for_r;      /*!< what to do with position */
	mds_pbc_proc      pbc_for_f;      /*!< what to do with pairs    */
	Real              K;              /*!< kinetic   energy         */
	Real              V;              /*!< potential energy         */
	Real              W;              /*!< Virial                   */
}
mds_frame;

#define MDS_FRAME_INIT { 0, 0, NULL, 0, NULL, { 0, 0, 0 , {0} }, NULL, NULL, 0,0,0  }

/** \brief Frame setup.
 *
 *  Set memory part to zero the allocate memory. After this call,
 *	the masses, masses inverses, positions and velocities must be set.
 *  The box, PBCs and scalar terms are untouched.
 *
 *	\param frame destination frame.
 *	\param num_particles > 0
 *	\param num_sets > 0
 *	\return 0 upon success, -1 upon failure.
 *
 *	- The masses should be stored in the info.mass field of the VELOCITIES.
 *	- The masses inverses should be stored in the info.inv_mass of the POSITIONS.
 *	- Per particle settings should be stored in the info.data of the ACCELERATIONS.
 */
int  mds_frame_load( mds_frame *frame, size_t num_particles, size_t num_sets );

/** \brief Frame destruction.
 *	\param frame previously created frame.
 */
void mds_frame_quit( mds_frame *frame );

/** \brief Helper to initialize positions.
 *
 *	Call mds_position_initialize.
 *	\param frame previously created frame.
 */
void mds_frame_initialize_positions( mds_frame *frame );

/** \brief Helper to initialize positions.
 *
 *	Call mds_velocity_initialize.
 *	\param frame previously created frame.
 *	\param Temperature in Kelvin.
 */
void mds_frame_initialize_velocities( mds_frame *frame, Real Temperature);

/** \brief Update current kinetic energy.
 *	call frame->K = mds_velocity_kinetic_energy( frame->sets[MDS_VELOCITY], frame->num_particles )
 *	\param frame
 */
void mds_frame_update_kinetic_energy( mds_frame *frame );

void mds_frame_NVE_T_and_PV( const mds_frame *frame, Real *T, Real *PV );
Real mds_frame_T( const mds_frame *frame );


/** \brief Set forces/accelerations to 0.
 */
void mds_frame_no_forces( mds_frame *frame );

void mds_frame_rescale( mds_frame *frame, const mds_vector *box );


#endif
